package com.lushu.chapitre1.engine
{
    import com.lushu.chapitre1.events.GameEngineEvent;
    import com.lushu.chapitre1.events.MenuEvent;
    import com.lushu.chapitre1.graphics.controls.ConfigurableMenu;
    import com.lushu.chapitre1.graphics.elements.MovableElement;
    import com.lushu.chapitre1.graphics.elements.animals.Animal;
    import com.lushu.chapitre1.graphics.elements.characters.Character;
    import com.lushu.chapitre1.graphics.elements.characters.EnemyCharacter;
    import com.lushu.chapitre1.graphics.elements.characters.ForceCharacter;
    import com.lushu.chapitre1.graphics.elements.enums.AnimatedObjectType;
    import com.sfdk.core.KeyboardListener;
    import com.sfdk.graphics.api.IDisplayObjectContainerEx;
    import com.sfdk.graphics.core.SpriteEx;
    import com.sfdk.graphics.engine.GraphicEngine;
    import com.sfdk.graphics.engine.data.EnemyDefinition;
    import com.sfdk.graphics.engine.data.ForceDefinition;
    import com.sfdk.graphics.engine.data.Map;
    import com.sfdk.graphics.engine.data.NPCDefinition;
    import com.sfdk.pools.BitmapDataPool;
    import com.sfdk.pools.MusicPool;
    import com.sfdk.utils.IntPoint;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.TimerEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundTransform;
    import flash.ui.Keyboard;
    import flash.utils.Dictionary;
    import flash.utils.Timer;

    public class GameEngine extends EventDispatcher
    {
        private var _mainWindow:IDisplayObjectContainerEx;
        private var _mainLoopTimer:Timer;

        private var _graphicEngine:GraphicEngine;
        private var _menuEngine:MenuEngine;
        private var _battleEngine:BattleEngine;

        private var _currentMusic:Sound;
        private var _currentMusicChannel:SoundChannel;

        private var _map:Map;

        private const SCALE:Number = 2;

        private var _currentCharacter:Character;
        private var _objectMoveMap:Vector.<Vector.<int>>;

        private var _terrainCostMapping:Dictionary;

        ShiningForceFont;
        ShiningForceSysFont;
        // 496 // 448 -> 248 / 224

        public function GameEngine(mainWindow:IDisplayObjectContainerEx, width:int = 248, height:int = 224, xPos:int = 0, yPos:int = 0) {
            _mainWindow = mainWindow;

            _graphicEngine = new GraphicEngine(width, height, SCALE, false);
            _graphicEngine.gridLayer.visible = false;
            _mainWindow.attachChild(_graphicEngine, xPos, yPos, "gameEngine");

            _battleDetails = new SpriteEx();
            _battleDetails.alpha = 0;
            _battleDetails.scaleX = SCALE;
            _battleDetails.scaleY = SCALE;
            _battleDetails.graphics.beginFill(0);
            _battleDetails.graphics.drawRect(0, 0, 248, 224)
            _mainWindow.attachChild(_battleDetails, 0, 0, "battleImage");

            _menuEngine = new MenuEngine(SCALE);
            _mainWindow.attachChild(_menuEngine, xPos, yPos, "menuEngine");

            _battleEngine = new BattleEngine();

            _map = new Map("http://dev.lushu.org/sfdk/maps/data/", "Granseal_Battle.map");
            _map.addEventListener("mapCreated", onMapCreated);

            KeyboardListener.instance.addEventListener("LEFT", handleArrowKeys);
            KeyboardListener.instance.addEventListener("RIGHT", handleArrowKeys);
            KeyboardListener.instance.addEventListener("UP", handleArrowKeys);
            KeyboardListener.instance.addEventListener("LEFT", handleArrowKeys);
            KeyboardListener.instance.addEventListener("SPACE", handleSpaceBar);
            KeyboardListener.instance.addEventListener("ENTER", handleEnterKey);

            KeyboardListener.instance.addEventListener("Keyboard-49", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-50", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-51", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-52", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-53", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-54", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-55", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-56", onLayerSwitch);
            KeyboardListener.instance.addEventListener("Keyboard-57", onLayerSwitch);


            _menuEngine.addEventListener(MenuEvent.STAY, onEndTurn);
            _menuEngine.addEventListener(MenuEvent.ATTACK, onAttackAction);
            _menuEngine.addEventListener(MenuEvent.SHOW_MENU, onShowMenu);

            _terrainCostMapping = new Dictionary();
            _terrainCostMapping["slow"] = new Dictionary();
            _terrainCostMapping["slow"][-1] = 1; //Grass
            _terrainCostMapping["slow"][1] = 99; //Grass
            _terrainCostMapping["slow"][2] = 3; //Dirt
            _terrainCostMapping["slow"][3] = 3; //Sand
            _terrainCostMapping["slow"][4] = 3; //Foret
            _terrainCostMapping["slow"][5] = 1.5; //HauteHerbe

            _terrainCostMapping["moderate"] = new Dictionary();
            _terrainCostMapping["moderate"][-1] = 1; //Grass
            _terrainCostMapping["moderate"][1] = 99; //Grass
            _terrainCostMapping["moderate"][2] = 1.5; //Dirt
            _terrainCostMapping["moderate"][3] = 2; //Sand
            _terrainCostMapping["moderate"][4] = 1.5; //Foret
            _terrainCostMapping["moderate"][5] = 1.5; //HauteHerbe

            _terrainCostMapping["flier"] = new Dictionary();
            _terrainCostMapping["flier"][-1] = 1; //Grass
            _terrainCostMapping["flier"][1] = 1; //Grass
            _terrainCostMapping["flier"][2] = 1; //Dirt
            _terrainCostMapping["flier"][3] = 1; //Sand
            _terrainCostMapping["flier"][4] = 1; //Foret
            _terrainCostMapping["flier"][5] = 1; //HauteHerbe

        }

        private var _intensityPos:Number;
        private var _currentMode:String;
        private var _availableTargets:Vector.<Character>;
        private var _currentTarget:Character;
        private var _nearestParticipant:Character;
        private var _gizmoAttack1:Bitmap;
        private var _gizmoAttack2:Bitmap;
        private var _gizmoAnim:Array;
        private var _bowieIdle1BitmapData:BitmapData;

        private function onShowMenu(e:Event = null):void {
            var characterPosition:IntPoint = _currentCharacter.tileBasedPosition;
            var enemyPosition:IntPoint;
            var hasNeighbors:Boolean;
            for each(var battleParticipant:MovableElement in _battleParticipant) {
                if (battleParticipant != _currentCharacter && battleParticipant.team != _currentCharacter.team) {
                    enemyPosition = battleParticipant.tileBasedPosition;
                    if ((Math.abs(enemyPosition.x - characterPosition.x) == 1 && Math.abs(enemyPosition.y - characterPosition.y) == 0) ||
                            (Math.abs(enemyPosition.x - characterPosition.x) == 0 && Math.abs(enemyPosition.y - characterPosition.y) == 1)) {
                        hasNeighbors = true;
                    }
                }
            }
            if (hasNeighbors) {
                _menuEngine.setDefaultAction(ConfigurableMenu.ATTACK_BTN.name);
            }
        }

        private function onAttackAction(e:Event = null):void {
            var characterPosition:IntPoint = _currentCharacter.tileBasedPosition;
            var enemyPosition:IntPoint;
            _availableTargets = new Vector.<Character>();
            for each(var battleParticipant:MovableElement in _battleParticipant) {
                if (battleParticipant != _currentCharacter && battleParticipant.team != _currentCharacter.team) {
                    enemyPosition = battleParticipant.tileBasedPosition;
                    if ((Math.abs(enemyPosition.x - characterPosition.x) == 1 && Math.abs(enemyPosition.y - characterPosition.y) == 0) ||
                            (Math.abs(enemyPosition.x - characterPosition.x) == 0 && Math.abs(enemyPosition.y - characterPosition.y) == 1)) {
                        _availableTargets.push(battleParticipant);
                    }
                }
            }
            if (_availableTargets.length) {
                _currentTarget = _availableTargets[0];
                enemyPosition = _currentTarget.tileBasedPosition;

                _currentCharacter.setDirection(enemyPosition.x - characterPosition.x, enemyPosition.y - characterPosition.y);
                _currentMode = "attack";
                _selectTile.isVisible = true;
                _selectTile.x = characterPosition.x * 24;
                _selectTile.y = characterPosition.y * 24;
                var position:Vector.<IntPoint> = new Vector.<IntPoint>();
                position.push(new IntPoint(enemyPosition.x, enemyPosition.y));
                _selectTile.moveTo(position);
                _selectTile.addEventListener("movementDone", onAttackActionBegin);
            }
            else {

            }
        }

        private function onAttackActionBegin(event:Event):void {
            _selectTile.removeEventListener("movementDone", onAttackActionBegin);
            _menuEngine.setCurrentEnemy(_currentTarget.characterDefinition);
        }


        private function onEndTurn(e:Event = null):void {
            _menuEngine.hasOpenMenu = false;
            _selectTile.isVisible = false;
            _bowieIndex = 0;
            _battleDetails.removeAllChildren();
            _battleBackground = null;
            _battleBG = null;


            _currentTarget = null;
            _currentCharacter.isVisible = true;
            _currentCharacter.saveTurnState();
            _intensityPos = 0;

            _poussinIndex += 1;
            _poussinIndex = _poussinIndex % _battleParticipant.length;
            _currentCharacter = _battleParticipant[_poussinIndex];
            _selectTile.x = _currentCharacter.x;
            _selectTile.y = _currentCharacter.y;
            _menuEngine.setCurrentCharacter(_currentCharacter.characterDefinition)
            _map.clearTempWalkable();
            for each(var battleParticipant:MovableElement in _battleParticipant) {
                if (battleParticipant != _currentCharacter && battleParticipant.team != _currentCharacter.team)
                    _map.addTempUnwalkable(battleParticipant.turnStartPos);
            }
            _graphicEngine.setAsCamera(_currentCharacter, true);

            var initPos:IntPoint = _currentCharacter.turnStartPos;
            var spread:int = _currentCharacter.moveStat;

            var x:int = 0;
            var y:int = 0;
            var tx:int = 0;
            var ty:int = 0;
            var width:int = 1 + spread * 2;
            var height:int = 1 + spread * 2;
            var colorWalk:uint = 0x000001;
            var colorUnWalk:uint = 0x000002;

            var objectMoveMap:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>(width);
            for (x = 0; x < width; x++) {
                objectMoveMap[x] = new Vector.<Number>(height);
            }
            fillAvailableMove(objectMoveMap, spread, spread, spread, spread);

            var image:BitmapData = new BitmapData(width, height, false);
            for (x = 0; x < width; x++) {
                for (y = 0; y < height; y++) {
                    tx = x - spread + initPos.x;
                    ty = y - spread + initPos.y;
                    if (Math.abs(initPos.x - tx) + Math.abs(initPos.y - ty) < spread && objectMoveMap[x][y] != 0)
                        image.setPixel(x, y, colorWalk);
                    else
                        image.setPixel(x, y, colorUnWalk);
                }
            }
            var currentColor:uint = 0x000003;
            for (x = 0; x < width; x++) {
                for (y = 0; y < height; y++) {
                    if (image.getPixel(x, y) == colorWalk) {
                        image.floodFill(x, y, currentColor);
                        currentColor++;
                    }
                }
            }
            var targetColor:uint = image.getPixel(spread, spread);
            _objectMoveMap = new Vector.<Vector.<int>>(width);
            for (x = 0; x < width; x++) {
                _objectMoveMap[x] = new Vector.<int>(height);
                for (y = 0; y < height; y++) {
                    if (targetColor == image.getPixel(x, y))
                        _objectMoveMap[x][y] = 1;
                    else
                        _objectMoveMap[x][y] = 0;
                }
            }

            for each(battleParticipant in _battleParticipant) {
                if (battleParticipant != _currentCharacter && battleParticipant.team == _currentCharacter.team)
                    _map.addTempUnwalkable(battleParticipant.turnStartPos);
            }

            if (_currentCharacter.team == 0) {
                var dest:Vector.<IntPoint> = new Vector.<IntPoint>();
                var tilePosition:IntPoint = _currentCharacter.tileBasedPosition;
                // Find nearest from the other team
                var nearestParticipant:MovableElement = null;
                for each(var battleParticipantC:Character in _battleParticipant) {
                    if (battleParticipantC.team == 1) {
                        _currentTarget = battleParticipantC;
                    }
                }
                if (_currentTarget != null && ((Math.abs(_currentTarget.tileBasedPosition.x - _currentCharacter.tileBasedPosition.x) == 1 && Math.abs(_currentTarget.tileBasedPosition.y - _currentCharacter.tileBasedPosition.y) == 0) ||
                        (Math.abs(_currentTarget.tileBasedPosition.x - _currentCharacter.tileBasedPosition.x) == 0 && Math.abs(_currentTarget.tileBasedPosition.y - _currentCharacter.tileBasedPosition.y) == 1))) {
                    dest.push(new IntPoint(tilePosition.x, tilePosition.y));
                }
                else {
                    var destX:int = tilePosition.x - 2;
                    if (destX > 0)
                        dest.push(new IntPoint(destX, tilePosition.y));
                    else
                        dest.push(new IntPoint(tilePosition.x, tilePosition.y));
                }


                _currentCharacter.moveTo(dest);
                _currentCharacter.addEventListener("movementDone", onEnemyMovementDone);
            }

        }

        private function onEnemyMovementDone(e:Event):void {
            _currentCharacter.removeEventListener("movementDone", onEnemyMovementDone);
            if (_currentTarget != null && ((Math.abs(_currentTarget.tileBasedPosition.x - _currentCharacter.tileBasedPosition.x) == 1 && Math.abs(_currentTarget.tileBasedPosition.y - _currentCharacter.tileBasedPosition.y) == 0) ||
                    (Math.abs(_currentTarget.tileBasedPosition.x - _currentCharacter.tileBasedPosition.x) == 0 && Math.abs(_currentTarget.tileBasedPosition.y - _currentCharacter.tileBasedPosition.y) == 1))) {

                _currentCharacter.setDirection(_currentTarget.tileBasedPosition.x - _currentCharacter.tileBasedPosition.x, _currentTarget.tileBasedPosition.y - _currentCharacter.tileBasedPosition.y);
                _currentMode = "attack2";
                _selectTile.isVisible = true;
                _selectTile.x = _currentCharacter.tileBasedPosition.x * 24;
                _selectTile.y = _currentCharacter.tileBasedPosition.y * 24;
                var position:Vector.<IntPoint> = new Vector.<IntPoint>();
                position.push(new IntPoint(_currentTarget.tileBasedPosition.x, _currentTarget.tileBasedPosition.y));
                _selectTile.moveTo(position);
                _selectTile.addEventListener("movementDone", onAttackActionBeginEnemy);
            }
            else {
                this.onEndTurn();
            }

        }

        private function onAttackActionBeginEnemy(event:Event):void {
            _selectTile.removeEventListener("movementDone", onAttackActionBeginEnemy);
            _menuEngine.setCurrentCharacter(_currentTarget.characterDefinition);
            _menuEngine.setCurrentEnemy(_currentCharacter.characterDefinition);

            // Fade to black then to battle background + info

            _menuEngine.switchToBattleMode();
            _battleBackground = new SpriteEx();
            _battleBackground.alpha = 0;

            _battleBG = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/background-9.png");

            _battleDetails.attachChild(_battleBackground, 0, 0, "battleBackground");
            _battleBackground.attachChild(_battleBG, 248 - _battleBG.width, (224 - _battleBG.height) / 2 - 8, "battleBG");

            var dirtGround:Bitmap = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/dirtGround.png");
            _battleBackground.attachChild(dirtGround, 130, 140, "dirtGround");

            _bowieIdle1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieIdle1.png");
            _bowieIdle1BitmapData = new BitmapData(_bowieIdle1.width, _bowieIdle1.height);
            _bowieIdle1BitmapData.copyPixels(_bowieIdle1.bitmapData, new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), new Point());
            _bowieIdle2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieIdle2.png");
            _bowieAttack1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieAttack1.png");
            _bowieAttack2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieAttack2.png");
            _sword1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSword1.png");
            _sword2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSword2.png");
            _swordUp = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSwordUp.png");
            _sword3 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSword3.png");
            _bowieIdle2.visible = false;
            _bowieAttack1.visible = false;
            _bowieAttack2.visible = false;
            _sword2.visible = false;
            _swordUp.visible = false;
            _sword3.visible = false;
            _bowieIndex = 0;
            _bowieAnim = [_bowieIdle1, _bowieIdle2, _bowieIdle1, _bowieIdle2, _bowieIdle1, _bowieIdle2, _bowieIdle1, _bowieIdle2, _bowieIdle1];
            _swordAnim = [_sword1, _sword1, _sword1, _sword1, _sword1, _sword1, _sword1, _sword1, _sword1];

            _battleBackground.attachChild(_sword1, 114, 74, "sword1");
            _battleBackground.attachChild(_bowieIdle1, 130, 64, "bowieIdle1");
            _battleBackground.attachChild(_bowieIdle2, 130, 64, "bowieIdle2");

            _gizmoIdle1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/gizmoIdle1.png");
            _gizmoInitialBitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
            _gizmoInitialBitmapData.copyPixels(_gizmoIdle1.bitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
            _gizmoIdle2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/gizmoIdle2.png");
            _gizmoInitialBitmapData2 = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
            _gizmoInitialBitmapData2.copyPixels(_gizmoIdle2.bitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
            _gizmoIdle2.visible = false;
            _gizmoInitialBitmapData2.copyPixels(_gizmoIdle2.bitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
            _gizmoIdle2.visible = false;
            _gizmoAttack1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/gizmoAttack1.png");
            _gizmoAttack1.visible = false;
            _gizmoAttack2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/gizmoAttack2.png");
            _gizmoAttack2.visible = false;

            _gizmoAnim = [_gizmoIdle1, _gizmoIdle2, _gizmoAttack1, _gizmoAttack1, _gizmoAttack2, _gizmoAttack2, _gizmoAttack2, _gizmoAttack2, _gizmoAttack2];


            _battleBackground.attachChild(_gizmoIdle1, 10, 48, "gizmoIdle1");
            _battleBackground.attachChild(_gizmoIdle2, 10, 48, "gizmoIdle2");
            _battleBackground.attachChild(_gizmoAttack1, 10, 48, "gizmoAttack1");
            _battleBackground.attachChild(_gizmoAttack2, 10, 48, "gizmoAttack2");

        }

        private function fillAvailableMove(map:Vector.<Vector.<Number>>, tx:int, ty:int, spread:Number, initSpread:Number):void {
            if (spread <= 0 || tx < 0 || ty < 0 || tx >= map.length || ty >= map[0].length || isNaN(spread))
                return;
            var initPos:IntPoint = _currentCharacter.turnStartPos;
            if (map[tx][ty] < spread)
                map[tx][ty] = spread;
            // Left
            //var left:Number = _terrainCostMapping[_currentCharacter.unitMoveType][_map.getWalkableValue(initPos.x + (tx - 1 - initSpread), initPos.y + (ty - initSpread))];
            var left:Boolean = _map.isWalkable(initPos.x + (tx - 1 - initSpread), initPos.y + (ty - initSpread));
            if (left)
                fillAvailableMove(map, tx - 1, ty, spread - 1, initSpread);
            //var right:Number = _terrainCostMapping[_currentCharacter.unitMoveType][_map.getWalkableValue(initPos.x + (tx + 1 - initSpread), initPos.y + (ty - initSpread))];
            var right:Boolean = _map.isWalkable(initPos.x + (tx + 1 - initSpread), initPos.y + (ty - initSpread));
            if (right)
                fillAvailableMove(map, tx + 1, ty, spread - 1, initSpread);
            //var top:Number = _terrainCostMapping[_currentCharacter.unitMoveType][_map.getWalkableValue(initPos.x + (tx - initSpread), initPos.y + (ty - 1 - initSpread))];
            var top:Boolean = _map.isWalkable(initPos.x + (tx - initSpread), initPos.y + (ty - 1 - initSpread));
            if (top)
                fillAvailableMove(map, tx, ty - 1, spread - 1, initSpread);
            //var bottom:Number = _terrainCostMapping[_currentCharacter.unitMoveType][_map.getWalkableValue(initPos.x + (tx - initSpread), initPos.y + (ty + 1 - initSpread))];
            var bottom:Boolean = _map.isWalkable(initPos.x + (tx - initSpread), initPos.y + (ty + 1 - initSpread));
            if (bottom)
                fillAvailableMove(map, tx, ty + 1, spread - 1, initSpread);
        }


        private var _poussinIndex:int = 0;
        private var _targetDestX:int = -1;
        private var _targetDestY:int = -1;
        private var _npcSprite:Animal;
        private var _npcSpriteLimits:Rectangle;
        private var _waitFrame:int;
        private var _flashFrame:int = 6;
        private var _npcSpriteDialogue:String;
        private var _mapType:String;
        private var _enemyList:Vector.<EnemyCharacter>;
        private var _forceList:Vector.<ForceCharacter>;
        private var _battleParticipant:Vector.<Character>;
        private var _selectTile:MovableElement;
        private var _battleDetails:SpriteEx;
        private var _battleBackground:SpriteEx;
        private var _battleBG:Bitmap;
        private var _bowieIdle1:Bitmap;
        private var _bowieIdle2:Bitmap;
        private var _bowieAnimFrame:int;
        private var _sword1:Bitmap;
        private var _bowieAttack1:Bitmap;
        private var _bowieAttack2:Bitmap;
        private var _gizmoIdle1:Bitmap;
        private var _gizmoIdle2:Bitmap;
        private var _bowieAnim:Array;
        private var _bowieIndex:int;
        private var _gizmoInitialBitmapData:BitmapData;
        private var _gizmoInitialBitmapData2:BitmapData;
        private var _sword2:Bitmap;
        private var _sword3:Bitmap;
        private var _swordUp:Bitmap;
        private var _swordAnim:Array;
        private var _enemyDeathAnim:Array;
        private var _enemyDeathFrame:int;


        private function onLoop(timerEvent:Event):void {
            var forceObject:ForceCharacter;
            for each(forceObject in _forceList) {
                forceObject.update(false);
            }
            var enemy:EnemyCharacter;
            for each(enemy in _enemyList) {
                enemy.update(false);
            }
            _selectTile.update(false);
            if (_npcSprite && !_npcSprite.isMoving) {
                if (_waitFrame <= 0) {
                    var initX:int = int(_npcSprite.x / (24));
                    var initY:int = int(_npcSprite.y / (24));
                    var destX:int;
                    var destY:int;
                    var dest:int = int(Math.random() * 4);
                    switch (dest) {
                        case 0:
                            destX = initX;
                            destY = initY + 1;
                            break;

                        case 1:
                            destX = initX;
                            destY = initY - 1;
                            break;

                        case 2:
                            destX = initX + 1;
                            destY = initY;
                            break;

                        case 3:
                            destX = initX - 1;
                            destY = initY;
                            break;
                    }

                    if (_map.isWalkable(destX, destY) && !(destX == _currentCharacter.movementInitX && destY == _currentCharacter.movementInitY) && !(destX == _currentCharacter.movementDestX && destY == _currentCharacter.movementDestY)) {
                        //solution = _aStar.solve(new IntPoint(initX, initY), new IntPoint(destX, destY));
                        var solution:Vector.<IntPoint> = new Vector.<IntPoint>();
                        solution.push(new IntPoint(destX, destY));
                        _npcSprite.moveTo(solution);
                    }
                    _waitFrame = 22;
                }
                else {
                    _waitFrame--;
                }
            }
            if (_npcSprite)
                _npcSprite.update(false);

            var initPos:IntPoint = _currentCharacter.turnStartPos;
            var spread:int = _currentCharacter.moveStat;

            var g:Graphics = _graphicEngine.overGridLayer.graphics;
            g.clear();
            g.beginFill(0x000000, 0.05 + 0.25 * Math.sin(_intensityPos));

            if (!_menuEngine.hasOpenMenu) {
                _currentCharacter.isVisible = true;
                // Take a square of moveStat * 2 X moveStat * 2 around the center

                for (var i:int = 0; i < 1 + 2 * spread; i++) {
                    for (var j:int = 0; j < 1 + 2 * spread; j++) {
                        var tx:int = i - spread + initPos.x;
                        var ty:int = j - spread + initPos.y;

                        if (_objectMoveMap[i][j] == 1) {
                            g.drawRect(tx * 24 - _graphicEngine.scrollX, ty * 24 - _graphicEngine.scrollY, 24, 24);
                        }
                    }
                }
            }
            else {
                if (_flashFrame > 0)
                    _flashFrame--;
                else {
                    _currentCharacter.isVisible = !_currentCharacter.isVisible;
                    _flashFrame = 6;
                }
                if (_currentMode == "attack") {
                    var currentPos:IntPoint = _currentCharacter.tileBasedPosition;
                    g.drawRect((currentPos.x - 1) * 24 - _graphicEngine.scrollX, currentPos.y * 24 - _graphicEngine.scrollY, 24, 24);
                    g.drawRect((currentPos.x + 1) * 24 - _graphicEngine.scrollX, currentPos.y * 24 - _graphicEngine.scrollY, 24, 24);
                    g.drawRect(currentPos.x * 24 - _graphicEngine.scrollX, (currentPos.y - 1) * 24 - _graphicEngine.scrollY, 24, 24);
                    g.drawRect(currentPos.x * 24 - _graphicEngine.scrollX, (currentPos.y + 1) * 24 - _graphicEngine.scrollY, 24, 24);
                }
            }
            _intensityPos += 0.3;


            if (KeyboardListener.instance.isKeyCodePressed(Keyboard.LEFT)) {
                handleArrowKeys(new Event("LEFT"));
            }
            else if (KeyboardListener.instance.isKeyCodePressed(Keyboard.UP)) {
                handleArrowKeys(new Event("UP"));
            }
            else if (KeyboardListener.instance.isKeyCodePressed(Keyboard.RIGHT)) {
                handleArrowKeys(new Event("RIGHT"));
            }
            else if (KeyboardListener.instance.isKeyCodePressed(Keyboard.DOWN)) {
                handleArrowKeys(new Event("DOWN"));
            }
            _graphicEngine.update();
            _menuEngine.update();

            if (_currentMode == "attack" && _battleBackground && _battleDetails && _battleDetails.alpha < 1 && _bowieIndex == 0) {
                _battleDetails.alpha += 0.05;
            }

            else if (_currentMode == "attack" && _battleBackground && _battleDetails && _battleDetails.alpha >= 1 && _battleBackground.alpha < 1 && _bowieIndex == 0) {
                _battleBackground.alpha += 0.05;
                if (_battleBackground.alpha > 0.5) {
                    _battleBG.x += 0.4;
                }
            }
            else if (_currentMode == "attack" && _battleBackground && _battleDetails && _bowieIndex < (_bowieAnim.length - 1)) {
                _bowieAnimFrame--;
                if (_bowieAnimFrame < 0) {
                    _bowieAnim[_bowieIndex].visible = !_bowieAnim[_bowieIndex].visible;
                    _swordAnim[_bowieIndex].visible = !_swordAnim[_bowieIndex].visible;
                    _bowieIndex++;
                    _bowieAnim[_bowieIndex].visible = !_bowieAnim[_bowieIndex].visible;
                    _swordAnim[_bowieIndex].visible = !_swordAnim[_bowieIndex].visible;


                    if (_bowieIndex != 4 && _bowieIndex != 5) {
                        _gizmoIdle1.visible = !_gizmoIdle1.visible;
                        _gizmoIdle2.visible = !_gizmoIdle2.visible;
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        _gizmoIdle1.bitmapData = gizmoBitmapData;
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData2, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        _gizmoIdle2.bitmapData = gizmoBitmapData;
                        _gizmoIdle1.x = 10;
                        _gizmoIdle1.y = 48;
                        _gizmoIdle2.x = 10;
                        _gizmoIdle2.y = 48;
                    }


                    /*  +8 + 4 // Sombre
                     + 0 - 12 // Sombre encore
                     -20 +14 // Brillant
                     +8 +8 // Normal*/
                    _bowieAnimFrame = 16;
                }
                if (_bowieIndex == 2 && _bowieAnimFrame > 12) {
                    _swordUp.visible = false
                    _bowieAttack1.y = 64;
                    _sword2.visible = true;
                }
                else if (_bowieIndex == 2) {
                    _swordUp.visible = true;
                    _bowieAttack1.y = 56;
                    _sword2.visible = false
                }
                else if (_bowieIndex == 4) {
                    if (_bowieAnimFrame > 14) {
                        _gizmoIdle1.visible = true;
                        _gizmoIdle2.visible = false;
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        var colorTransform:ColorTransform = new ColorTransform(0.5, 0.5, 0.5);
                        gizmoBitmapData.colorTransform(new Rectangle(0, 0, _gizmoIdle2.width, _gizmoIdle2.height), colorTransform);
                        _gizmoIdle1.bitmapData = gizmoBitmapData;
                        _gizmoIdle1.x = 14;
                        _gizmoIdle1.y = 50;
                    }
                    else if (_bowieAnimFrame > 12) {
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        var colorTransform:ColorTransform = new ColorTransform(0.5, 0.5, 0.5);
                        gizmoBitmapData.colorTransform(new Rectangle(0, 0, _gizmoIdle2.width, _gizmoIdle2.height), colorTransform);
                        _gizmoIdle1.bitmapData = gizmoBitmapData;
                        _gizmoIdle1.x = 14;
                        _gizmoIdle1.y = 44;
                    }
                    else if (_bowieAnimFrame > 10) {
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        var colorTransform:ColorTransform = new ColorTransform(3, 3, 3);
                        gizmoBitmapData.colorTransform(new Rectangle(0, 0, _gizmoIdle2.width, _gizmoIdle2.height), colorTransform);
                        _gizmoIdle1.bitmapData = gizmoBitmapData;
                        _gizmoIdle1.x = 4;
                        _gizmoIdle1.y = 52;
                    }
                    else if (_bowieAnimFrame > 8) {
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        var colorTransform:ColorTransform = new ColorTransform(1, 1, 1);
                        gizmoBitmapData.colorTransform(new Rectangle(0, 0, _gizmoIdle2.width, _gizmoIdle2.height), colorTransform);
                        _gizmoIdle1.bitmapData = gizmoBitmapData;
                        _gizmoIdle1.x = 8;
                        _gizmoIdle1.y = 56;
                    }
                    else if (_bowieAnimFrame >= 6) {
                        var gizmoBitmapData:BitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                        gizmoBitmapData.copyPixels(_gizmoInitialBitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                        var colorTransform:ColorTransform = new ColorTransform(1, 1, 1);
                        gizmoBitmapData.colorTransform(new Rectangle(0, 0, _gizmoIdle2.width, _gizmoIdle2.height), colorTransform);
                        _gizmoIdle1.bitmapData = gizmoBitmapData;
                        _gizmoIdle1.x = 10;
                        _gizmoIdle1.y = 48;
                    }
                }
                else if (_bowieIndex == 3 && _bowieAnimFrame == 0) {
                    var multiplier = 0.75 + Math.random() * 0.25;
                    _currentTarget.characterDefinition.stats["hp"] -= int((_currentCharacter.characterDefinition.stats["atk"] - _currentTarget.characterDefinition.stats["def"]) * multiplier);
                    _currentTarget.characterDefinition.stats["hp"] = Math.max(0, _currentTarget.characterDefinition.stats["hp"]);
                    _menuEngine.setCurrentEnemy(_currentTarget.characterDefinition);
                }

            }
            else if (_currentMode == "attack" && _battleBackground && _battleDetails && _currentTarget.characterDefinition.stats["hp"] <= 0 && _bowieAnimFrame > 0) {
                var width2:int = _gizmoIdle2.width;
                var disappearingArray:Array = [
                    {x:0, y:0},
                    {x:width2 / 2,y:0},
                    {x:2, y: 1},
                    {x:width2 / 2 + 2, y:1},
                    {x:2, y: 0},
                    {x:width2 / 2 + 2, y:0},
                    {x:0, y:1},
                    {x:width2 / 2,y:1},
                    {x:3, y: 0},
                    {x:width2 / 2 + 3, y:0},
                    {x:1, y: 1},
                    {x:width2 / 2 + 1, y:1},
                    {x:3, y: 1},
                    {x:width2 / 2 + 3, y:1},
                    {x:1, y: 0},
                    {x:width2 / 2 + 1, y:0}
                ]
                var height2:int = _gizmoIdle2.height;
                var i:int = 0;
                var j:int = 0;

                for (i = 0; i < (width2 / 2); i = i + 4) {
                    for (j = 0; j < height2; j = j + 2) {
                        var aX:int = i + disappearingArray[16 - _bowieAnimFrame].x;
                        var aY:int = j + disappearingArray[16 - _bowieAnimFrame].y;
                        trace("Remove " + aX + " " + aY)
                        _gizmoIdle2.bitmapData.setPixel32(aX, aY, 0);
                    }

                }
                _bowieAnimFrame--;
            }
            else if (_currentMode == "attack" && _battleBackground && _battleDetails && _bowieIndex >= (_bowieAnim.length - 1) && _battleBackground.alpha > 0) {
                _menuEngine.visible = false;
                _battleBackground.alpha -= 0.05;
            }
            else if (_currentMode == "attack" && _battleBackground && _battleDetails && _bowieIndex >= (_bowieAnim.length - 1) && _battleDetails.alpha > 0) {
                _battleDetails.alpha -= 0.05;
            }
            else if (_currentMode == "attack" && _battleBackground && _battleDetails && _bowieIndex >= (_bowieAnim.length - 1)) {
                _menuEngine.visible = true;
                _menuEngine.switchToMoveMode();
                _currentMode = "move";
                if (_currentTarget.characterDefinition.stats["hp"] <= 0) {
                    // Enemy Death
                    _enemyDeathAnim = ["Gauche","Gauche","Gauche","Gauche","Dos","Dos", "Gauche", "Droite","Droite","Face","Face","Face",
                        "Gauche","Gauche","Gauche","Gauche","Dos","Dos", "Gauche", "Droite","Droite","Face","Face","Face",
                        "Gauche","Gauche","Gauche","Gauche","Dos","Dos", "Gauche", "Droite","Droite","Face","Face","Face",
                        "death1","death1","death1","death1","death1","death1","death1","death1",
                        "death2","death2","death2","death2","death2","death2","death2","death2",
                        "death3","death3","death3","death3","death3","death3","death3","death3"];
                    _enemyDeathFrame = 0;
                    _currentMode = "death";
                }
                else {
                    onEndTurn();
                }
            }

            if (_currentMode == "attack2" && _battleBackground && _battleDetails && _battleDetails.alpha < 1 && _bowieIndex == 0) {
                _battleDetails.alpha += 0.05;
            }

            else if (_currentMode == "attack2" && _battleBackground && _battleDetails && _battleDetails.alpha >= 1 && _battleBackground.alpha < 1 && _bowieIndex == 0) {
                if (_battleBackground.alpha > 0.5) {
                    _battleBG.x += 0.8;
                }
                _battleBackground.alpha += 0.05;

            }
            else if (_currentMode == "attack2" && _battleBackground && _battleDetails && _bowieIndex < (_bowieAnim.length - 1)) {
                _bowieAnimFrame--;
                if (_bowieAnimFrame < 0) {
                    _bowieAnim[_bowieIndex].visible = !_bowieAnim[_bowieIndex].visible;
                    _gizmoAnim[_bowieIndex].visible = !_gizmoAnim[_bowieIndex].visible;
                    _swordAnim[_bowieIndex].visible = !_swordAnim[_bowieIndex].visible;
                    _bowieIndex++;
                    _bowieAnim[_bowieIndex].visible = !_bowieAnim[_bowieIndex].visible;
                    _gizmoAnim[_bowieIndex].visible = !_gizmoAnim[_bowieIndex].visible;
                    _swordAnim[_bowieIndex].visible = !_swordAnim[_bowieIndex].visible;

                    _bowieAnimFrame = 16;
                }
                else if (_bowieIndex == 3 && _bowieAnimFrame == 0) {
                    var multiplier = 0.75 + Math.random() * 0.25;
                    _currentTarget.characterDefinition.stats["hp"] -= int((_currentCharacter.characterDefinition.stats["atk"] - _currentTarget.characterDefinition.stats["def"]) * multiplier);
                    _currentTarget.characterDefinition.stats["hp"] = Math.max(0, _currentTarget.characterDefinition.stats["hp"]);
                    _menuEngine.setCurrentCharacter(_currentTarget.characterDefinition);
                }
                if (_bowieIndex == 4) {
                    var eventArray:Array = [
                        {x:0, y:0, effect : 0},
                        {x:0, y:0, effect : 0},
                        {x:0, y:0, effect : 0},
                        {x:0, y:0, effect : 0},
                        {x:2, y:2, effect : 0},
                        {x:-2, y:-4, effect : 1},
                        {x:4, y:-4, effect : 2},
                        {x:0, y:2, effect : 1},
                        {x:-6, y:-4, effect : 2},
                        {x:0, y:8, effect : 1},
                        {x:6, y:6, effect : 2},
                        {x:0, y:4, effect : 1},
                        {x:6, y:2, effect : 2},
                        {x:4, y:7, effect : 0},
                        {x:2, y:8, effect : 0},
                        {x:8, y:6, effect : 0},
                        {x:3, y:4, effect : 0}
                    ];

                    var eventObj:Object = eventArray[16 - _bowieAnimFrame];
                    _battleBG.x = 0;
                    _battleBG.y = (224 - _battleBG.height) / 2 - 8 + eventObj.y;
                    _bowieIdle1.x = 130 + eventObj.x;
                    _bowieIdle1.y = 64 + eventObj.y;
                    _sword1.x = 114 + eventObj.x;
                    _sword1.y = 74 + eventObj.y;
                    if (eventObj.effect == 1) {
                        _battleDetails.graphics.clear();
                        _battleDetails.graphics.beginFill(0xa4a4a4);
                        _battleDetails.graphics.drawRect(0, 0, 248, 224);

                        var bowieBitmapData:BitmapData = new BitmapData(_bowieIdle1.width, _bowieIdle1.height);
                        bowieBitmapData.copyPixels(_bowieIdle1BitmapData, new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), new Point());
                        var colorTransform:ColorTransform = new ColorTransform(0.5, 0.5, 0.5);
                        bowieBitmapData.colorTransform(new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), colorTransform);
                        _bowieIdle1.bitmapData = bowieBitmapData;
                    }
                    else {
                        _battleDetails.graphics.clear();
                        _battleDetails.graphics.beginFill(0);
                        _battleDetails.graphics.drawRect(0, 0, 248, 224);

                        if (eventObj.effect == 2) {
                            var bowieBitmapData:BitmapData = new BitmapData(_bowieIdle1.width, _bowieIdle1.height);
                            bowieBitmapData.copyPixels(_bowieIdle1BitmapData, new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), new Point());
                            var colorTransform:ColorTransform = new ColorTransform(3, 3, 3);
                            bowieBitmapData.colorTransform(new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), colorTransform);
                            _bowieIdle1.bitmapData = bowieBitmapData;
                        }
                        else {
                            var bowieBitmapData:BitmapData = new BitmapData(_bowieIdle1.width, _bowieIdle1.height);
                            bowieBitmapData.copyPixels(_bowieIdle1BitmapData, new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), new Point());
                            var colorTransform:ColorTransform = new ColorTransform(1, 1, 1);
                            bowieBitmapData.colorTransform(new Rectangle(0, 0, _bowieIdle1.width, _bowieIdle1.height), colorTransform);
                            _bowieIdle1.bitmapData = bowieBitmapData;
                        }


                    }
                }
                else {
                    _bowieIdle1.x = 130;
                    _bowieIdle1.y = 64;
                    _sword1.x = 114;
                    _sword1.y = 74;
                    _battleBG.x = 0;
                    _battleBG.y = (224 - _battleBG.height) / 2 - 8;
                }

            }
            else if (_currentMode == "attack2" && _battleBackground && _battleDetails && _currentTarget.characterDefinition.stats["hp"] <= 0 && _bowieAnimFrame > 0) {
                var width2:int = _bowieIdle1.width;
                var disappearingArray:Array = [
                    {x:0, y:0},
                    {x:width2 / 2,y:0},
                    {x:2, y: 1},
                    {x:width2 / 2 + 2, y:1},
                    {x:2, y: 0},
                    {x:width2 / 2 + 2, y:0},
                    {x:0, y:1},
                    {x:width2 / 2,y:1},
                    {x:3, y: 0},
                    {x:width2 / 2 + 3, y:0},
                    {x:1, y: 1},
                    {x:width2 / 2 + 1, y:1},
                    {x:3, y: 1},
                    {x:width2 / 2 + 3, y:1},
                    {x:1, y: 0},
                    {x:width2 / 2 + 1, y:0}
                ]
                var height2:int = _bowieIdle1.height;
                var i:int = 0;
                var j:int = 0;

                for (i = 0; i < (width2 / 2); i = i + 4) {
                    for (j = 0; j < height2; j = j + 2) {
                        var aX:int = i + disappearingArray[16 - _bowieAnimFrame].x;
                        var aY:int = j + disappearingArray[16 - _bowieAnimFrame].y;
                        trace("Remove " + aX + " " + aY)
                        _bowieIdle1.bitmapData.setPixel32(aX, aY, 0);
                        _sword1.bitmapData.setPixel32(aX, aY, 0);
                    }

                }
                _bowieAnimFrame--;
            }
            else if (_currentMode == "attack2" && _battleBackground && _battleDetails && _bowieIndex >= (_bowieAnim.length - 1) && _battleBackground.alpha > 0) {
                _menuEngine.visible = false;
                _battleBackground.alpha -= 0.05;
            }
            else if (_currentMode == "attack2" && _battleBackground && _battleDetails && _bowieIndex >= (_bowieAnim.length - 1) && _battleDetails.alpha > 0) {
                _battleDetails.alpha -= 0.05;
            }
            else if (_currentMode == "attack2" && _battleBackground && _battleDetails && _bowieIndex >= (_bowieAnim.length - 1)) {
                _menuEngine.visible = true;
                _menuEngine.switchToMoveMode();
                _currentMode = "move";
                if (_currentTarget.characterDefinition.stats["hp"] <= 0) {
                    // Enemy Death
                    _enemyDeathAnim = ["Gauche","Gauche","Gauche","Gauche","Dos","Dos", "Gauche", "Droite","Droite","Face","Face","Face",
                        "Gauche","Gauche","Gauche","Gauche","Dos","Dos", "Gauche", "Droite","Droite","Face","Face","Face",
                        "Gauche","Gauche","Gauche","Gauche","Dos","Dos", "Gauche", "Droite","Droite","Face","Face","Face",
                        "death1","death1","death1","death1","death1","death1","death1","death1",
                        "death2","death2","death2","death2","death2","death2","death2","death2",
                        "death3","death3","death3","death3","death3","death3","death3","death3"];
                    _enemyDeathFrame = 0;
                    _currentMode = "death";
                }
                else {
                    onEndTurn();
                }
            }

            if (_currentMode == "death" && _enemyDeathFrame < _enemyDeathAnim.length) {
                _currentTarget.setFacing(_enemyDeathAnim[_enemyDeathFrame])
                _enemyDeathFrame++;
            }
            else if (_currentMode == "death") {
                _currentMode = "move";
                var idx:int = _battleParticipant.indexOf(_currentTarget);
                if (idx < _poussinIndex)
                    _poussinIndex--;
                _battleParticipant.splice(idx, 1);
                _graphicEngine.removeElement(_currentTarget);
                onEndTurn();
            }


        }

        private function onMapCreated(e:Event):void {
            _graphicEngine.loadMap(e.target as Map);
            _mapType = _map.mapType;

            var soundTransform:SoundTransform = new SoundTransform(0.5);
            _currentMusic = MusicPool.getFromPool("resources/music/" + _map.musicName);
            _currentMusicChannel = _currentMusic.play(0, 100, soundTransform);

            _selectTile = new Animal(AnimatedObjectType.ANIMATION_PATH + "/force/selectTil.pck", 4);
            _selectTile.isVisible = false;
            _graphicEngine.addElement(_selectTile);
            if (_mapType != "battle") {
                var type:Array = new Array();
                type[0] = AnimatedObjectType.POUSSIN;
                type[1] = AnimatedObjectType.COQ;
                type[2] = AnimatedObjectType.POULE;
                for (var i:int = 0; i < 1; i++) {
                    var poussinObject:Animal = new Animal(type[i], 2);
                    var notWalkable:Boolean = true;
                    while (notWalkable) {
                        poussinObject.x = (10 + Math.random() * 10) * 24;
                        poussinObject.y = (10 + Math.random() * 10) * 24;
                        if (!_map.isWalkable(poussinObject.x / (24), poussinObject.y / (24)))
                            notWalkable = true;
                        else
                            notWalkable = false;
                    }
                    _graphicEngine.addElement(poussinObject);
                    var path:Vector.<IntPoint> = new Vector.<IntPoint>();
                    path.push(new IntPoint(poussinObject.x / (24), poussinObject.y / (24)));
                    poussinObject.moveTo(path);
                    poussinObject.saveTurnState();
                }
                //_currentCharacter = poussinObject;
                _graphicEngine.setAsCamera(_currentCharacter);

                var npcList:Vector.<NPCDefinition> = _map.npcList;
                var npcCount:int = npcList.length;
                for (var j:int = 0; j < npcCount; j++) {
                    _npcSprite = new Animal(AnimatedObjectType.ANIMATION_PATH + npcList[j].spriteName + ".pck", 0.8)
                    _npcSpriteLimits = npcList[j].limits;
                    _npcSpriteDialogue = npcList[j].textName;
                    notWalkable = true;
                    while (notWalkable) {
                        _npcSprite.x = (npcList[j].limits.left + Math.random() * (npcList[j].limits.width)) * 24
                        _npcSprite.y = (npcList[j].limits.top + Math.random() * (npcList[j].limits.height)) * 24
                        if (!_map.isWalkable(_npcSprite.x / (24), _npcSprite.y / (24)))
                            notWalkable = true;
                        else
                            notWalkable = false;
                    }
                    _graphicEngine.addElement(_npcSprite);
                }
            }
            else {
                _battleParticipant = new Vector.<Character>();
                var enemyList:Vector.<EnemyDefinition> = _map.enemyList;
                var enemyCount:int = enemyList.length;
                var enemyDefinition:EnemyDefinition;
                _enemyList = new Vector.<EnemyCharacter>();
                for (var k:int = 0; k < enemyCount; k++) {
                    enemyDefinition = enemyList[k];
                    var enemy:EnemyCharacter = new EnemyCharacter(enemyDefinition);
                    enemy.team = 0;
                    _enemyList.push(enemy);
                    enemy.saveTurnState();
                    _battleParticipant.push(enemy);
                    _graphicEngine.addElement(enemy);
                }

                var forceStartingPosition:Vector.<ForceDefinition> = _map.forceList;
                var forceDefinition:ForceDefinition;
                _forceList = new Vector.<ForceCharacter>();
                for (k = 0; k < forceStartingPosition.length; k++) {
                    forceDefinition = forceStartingPosition[k];
                    var forceCharacter:ForceCharacter = new ForceCharacter(forceDefinition);
                    forceCharacter.team = 1;

                    _forceList.push(forceCharacter);
                    forceCharacter.saveTurnState();
                    _battleParticipant.push(forceCharacter);
                    _currentCharacter = forceCharacter;
                    _graphicEngine.addElement(forceCharacter);
                    _graphicEngine.setAsCamera(forceCharacter);
                }

                onEndTurn();
            }
            dispatchEvent(new GameEngineEvent(GameEngineEvent.LOADED));

            _graphicEngine.update(null, true);

            _mainLoopTimer = new Timer(15, 0);
            _mainLoopTimer.addEventListener(TimerEvent.TIMER, onLoop);
            _mainLoopTimer.start();
        }

        private function handleSpaceBar(e:Event = null):void {
            if (_currentCharacter.team == 1) {
                if (_currentMode == "attack") {
                    _currentMode = "move";
                    var position:Vector.<IntPoint> = new Vector.<IntPoint>();
                    position.push(new IntPoint(_currentCharacter.tileBasedPosition.x, _currentCharacter.tileBasedPosition.y));
                    _selectTile.moveTo(position);
                    _menuEngine.setCurrentEnemy(null);
                    _selectTile.addEventListener("movementDone", onAttackActionEnd);
                }
                else {
                    if (_map.isWalkableUnder(_currentCharacter)) {
                        _menuEngine.handleSpaceBar(e);
                    }
                }
            }
        }

        private function onAttackActionEnd(event:Event):void {
            if (_currentCharacter.team == 1) {
                _selectTile.removeEventListener("movementDone", onAttackActionEnd);
                _menuEngine.handleSpaceBar(event);
                _selectTile.isVisible = false;
            }
        }

        private function handleEnterKey(e:Event):void {
            if (_currentCharacter.team == 1) {
                if (_currentMode == "attack") {
                    // Fade to black then to battle background + info

                    _menuEngine.switchToBattleMode();
                    _battleBackground = new SpriteEx();
                    _battleBackground.alpha = 0;

                    _battleBG = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/background-9.png");

                    _battleDetails.attachChild(_battleBackground, 0, 0, "battleBackground");
                    _battleBackground.attachChild(_battleBG, 248 - _battleBG.width, (224 - _battleBG.height) / 2 - 8, "battleBG");

                    var dirtGround:Bitmap = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/dirtGround.png");
                    _battleBackground.attachChild(dirtGround, 130, 140, "dirtGround");

                    _bowieIdle1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieIdle1.png");
                    _bowieIdle2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieIdle2.png");
                    _bowieAttack1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieAttack1.png");
                    _bowieAttack2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/bowieAttack2.png");
                    _sword1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSword1.png");
                    _sword2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSword2.png");
                    _swordUp = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSwordUp.png");
                    _sword3 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/woodenSword3.png");
                    _bowieIdle2.visible = false;
                    _bowieAttack1.visible = false;
                    _bowieAttack2.visible = false;
                    _sword2.visible = false;
                    _swordUp.visible = false;
                    _sword3.visible = false;
                    _bowieIndex = 0;
                    _bowieAnim = [_bowieIdle1, _bowieIdle2, _bowieAttack1, _bowieAttack1, _bowieAttack2, _bowieAttack2, _bowieAttack2, _bowieAttack2, _bowieAttack2];
                    _swordAnim = [_sword1, _sword1, _swordUp, _swordUp, _sword3, _sword3, _sword3, _sword3, _sword3];

                    _battleBackground.attachChild(_sword1, 114, 74, "sword1");
                    _battleBackground.attachChild(_sword2, 162, 46, "sword2");
                    _battleBackground.attachChild(_swordUp, 150, 36, "swordUP");
                    _battleBackground.attachChild(_sword3, 126, 90, "sword3");
                    _battleBackground.attachChild(_bowieIdle1, 130, 64, "bowieIdle1");
                    _battleBackground.attachChild(_bowieIdle2, 130, 64, "bowieIdle2");
                    _battleBackground.attachChild(_bowieAttack1, 130, 64, "bowieAttack1");
                    _battleBackground.attachChild(_bowieAttack2, 130, 64, "bowieAttack2");

                    _gizmoIdle1 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/gizmoIdle1.png");
                    _gizmoInitialBitmapData = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                    _gizmoInitialBitmapData.copyPixels(_gizmoIdle1.bitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                    _gizmoIdle2 = BitmapDataPool.instance.getAsBitmap("resources/images/battleBackgrounds/gizmoIdle2.png");
                    _gizmoInitialBitmapData2 = new BitmapData(_gizmoIdle1.width, _gizmoIdle1.height);
                    _gizmoInitialBitmapData2.copyPixels(_gizmoIdle2.bitmapData, new Rectangle(0, 0, _gizmoIdle1.width, _gizmoIdle1.height), new Point());
                    _gizmoIdle2.visible = false;
                    _battleBackground.attachChild(_gizmoIdle1, 10, 48, "gizmoIdle1");
                    _battleBackground.attachChild(_gizmoIdle2, 10, 48, "gizmoIdle2");
                }
                else if (!_menuEngine.handleEnterKey(e)) {


                }
            }
        }

        private function handleArrowKeys(e:Event):void {
            if (_currentCharacter.team == 1) {
                if (!_menuEngine.handleArrowKeys(e)) {
                    var initX:int = int(_currentCharacter.x / (24));
                    var initY:int = int(_currentCharacter.y / (24));
                    if (_currentMode == "attack") {
                        if (_availableTargets.length > 1) {
                            switch (e.type) {
                                case "LEFT" :
                                    destX = initX - 1;
                                    destY = initY;
                                    break;

                                case "UP" :
                                    destX = initX;
                                    destY = initY - 1;
                                    break;

                                case "RIGHT" :
                                    destX = initX + 1;
                                    destY = initY;
                                    break;

                                case "DOWN" :
                                    destX = initX;
                                    destY = initY + 1;
                                    break;
                            }
                            for each(var target:Character in _availableTargets) {
                                var targetPosition:IntPoint = target.tileBasedPosition;
                                if (targetPosition.x == destX && targetPosition.y == destY) {
                                    if (_selectTile.x != destX * 24 && _selectTile.y != destY * 24) {
                                        _selectTile.x = destX * 24;
                                        _selectTile.y = destY * 24;
                                        _currentTarget = target;
                                        _currentCharacter.setDirection(targetPosition.x - initX, targetPosition.y - initY);
                                        _menuEngine.setCurrentEnemy(_currentTarget.characterDefinition);
                                        MusicPool.getFromPool("resources/sounds/Menu Move.mp3").play();
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    else {
                        var solution:Vector.<IntPoint>;

                        var destX:int;
                        var destY:int;
                        switch (e.type) {
                            case "LEFT" :
                                destX = initX - 1;
                                destY = initY;
                                break;

                            case "UP" :
                                destX = initX;
                                destY = initY - 1;
                                break;

                            case "RIGHT" :
                                destX = initX + 1;
                                destY = initY;
                                break;

                            case "DOWN" :
                                destX = initX;
                                destY = initY + 1;
                                break;
                        }

                        var initPos:IntPoint = _currentCharacter.turnStartPos;
                        var spread:int = _currentCharacter.moveStat;
                        if (!_currentCharacter.isMoving &&
                                (_targetDestX != destX || _targetDestY != destY)
                                && _objectMoveMap[destX - initPos.x + spread][destY - initPos.y + spread]
                                ) {
                            //if (_map.isWalkable(destX, destY)){
                            //&& !(destX == _npcSprite.movementInitX && destY == _npcSprite.movementInitY) && !(destX == _npcSprite.movementDestX && destY == _npcSprite.movementDestY)) {
                            //solution = _aStar.solve(new IntPoint(initX, initY), new IntPoint(destX, destY));
                            solution = new Vector.<IntPoint>();
                            solution.push(new IntPoint(destX, destY));

                            if (solution != null) {
                                _currentCharacter.moveTo(solution);
                                _targetDestX = destX;
                                _targetDestY = destY;
                                trace("Destination " + destX + " " + destY);
                            }
                        }
                        else {
                            _currentCharacter.setDirection(destX - initX, destY - initY);
                        }
                    }

                }
            }
        }


        /** Debug Code **/

        private function onLayerSwitch(e:Event):void {
            var type:Array = e.type.split("-");
            var index:int = int(Number(type[1])) - 48;
            switch (index) {
                case 1 :
                    _map.solLayers[0].isVisible = !_map.solLayers[0].isVisible;
                    _graphicEngine.forceRefresh(_map.solLayers[0]);
                    break;

                case 2 :
                    _map.solLayers[1].isVisible = !_map.solLayers[1].isVisible;
                    _graphicEngine.forceRefresh(_map.solLayers[1]);
                    break;

                case 4 :
                    _map.joueurLayers[0].isVisible = !_map.joueurLayers[0].isVisible;
                    _graphicEngine.forceRefresh(_map.joueurLayers[0]);
                    break;

                case 5 :
                    _map.upperLayers[0].isVisible = !_map.upperLayers[0].isVisible;
                    _graphicEngine.forceRefresh(_map.upperLayers[0]);
                    break;

                case 6 :
                    _map.upperLayers[1].isVisible = !_map.upperLayers[1].isVisible;
                    _graphicEngine.forceRefresh(_map.upperLayers[1]);
                    break;

                case 8 :
                    _map.walkableLayer.isVisible = !_map.walkableLayer.isVisible;
                    _graphicEngine.forceRefresh(_map.walkableLayer);
                    break;
                case 9 :
                    _graphicEngine.gridLayer.visible = !_graphicEngine.gridLayer.visible;
                    break;
            }
        }
    }


}
